Kontrol Akışı
Kontrol akışı bir kod parçasını belirli şartın sağlanıp sağlanmaması durumunda nerede ne şekilde çalışacağını veya bir kodun tekrarlı olarak çalışıp çalışmayacağını ifade ederken kullanmamızdır.
Kontrol akışı ifadeleri kodlama dilleri için hayati önem sağlamaktadır. Rust içerisinde yaygın kullanılan bir adet koşullu durumun ifadesi olan if
ve 3 adet döngü bulunmaktadır.
If İfadesi
İlk olarak if
ifadesi ile başlayabiliriz. If türkçeğe eğer
olarak çevirilmektedir ve bir şartın gerçekleşmesi koşuluyla içerisindeki kodları çalıştırmaktadır. Bir örnek ile bu yapıya bakıcak olursak:
let sayi = 1;
if sayi > 0 {
println!("Evet doğru, tebrikler artık birinci sınıf talebesini RUST kullanarak ezebilirsin");
} else {
println!("Olsun be devamsızlıktan kalma, seneye öğrenirsin");
}
Kodumuzu incelediğimizde ilk olarak bir değişken tanımladığımızı görebiliriz. Bu değişken 1
değerine sahip unsigned integer
bir değer olmaktadır. Sonrasında altında asıl önemli olan kısım if
koşulu bizleri karşılamaktadır. Bu koşul if
kelimesinden süslü parantezin başına kadar olan koşulun true
veya false
olmasını kontrol etmektedir. Eğer bu durum false
ise içinde olan kod çalışmaz ancak true
ise içinde olan kod çalışır. Bizim bu kod örneğimizde de sayı
olarak isimlendirdiğimiz değişken 0
dan büyük olduğu için koşulumuz true
döndürür ve iç kısmında bulunan println!()
makrosu çalışır. Peki şart sağlanmasaydı yani false
dönseydi ne olacaktı? O durumda da hemen altındaki else
yapısı devreye girecek ve else
kod blokları içerisindeki println!()
makrosu çalışacaktı.
Daha önceden bir fonksiyonun birden fazla çıktısının olabileceğini söylemiştik hadi if
ile birleştirerek bu olayı örneklendirelim. Fonksiyonumuz içerisine girilen sayı 10'dan büyükse Büyüktür
10'dan küçükse Küçüktür
çıktısı veren bir fonksiyon yazabiliriz.
fn buyuk_kucuk(deger:u64)-> String{
if deger > 10{
"büyüktür".to_string() // ";" yok
} else {
"küçüktür".to_string() // ";" yok
}
}
fn main() {
let durum:String = buyuk_kucuk(9);
println!("{}",durum); // küçüktür
let durum:String = buyuk_kucuk(11);
println!("{}",durum); // büyüktür
}
Yukarıda ifade edilen kodu inceleyerek nasıl bir şekilde fonksiyonlar ile akış elemanlarını kontrol ettiğimizi görüntüleyebilirsiniz.
Aynı zamanda Rust içerisinde de farklı şartları birbirine bağlayabiliriz. Bu işlemi else if
yapısı ile kontrol etmekteyiz. aynı if gibi bu yapıda da iç parantezine koşul almaktadır. Bu yapı else
yapısının kapsamadığı şartlardan birini oluşturmaktadır. Bu durumu göstermek için üst kısımda yazdığımız kodu biraz daha özelleştirebiliriz.
fn buyuk_kucuk_esit(deger:u64)-> String{
if deger > 10{
"büyüktür".to_string() // ";" yok
} else if deger < 10{
"küçüktür".to_string() // ";" yok
} else{
"eşittir".to_string() // ";" yok
}
}
fn main() {
let durum:String = buyuk_kucuk(9);
println!("{}",durum); // küçüktür
let durum:String = buyuk_kucuk(11);
println!("{}",durum); // büyüktür
let durum:String = buyuk_kucuk(10);
println!("{}",durum); // eşittir
}
Loop İfadesi
Looplar türkçeye döngüler olarak çevrilmektedir ve bir işlemi sonsuza kadar yapmaya yaramaktadır. İçlerine yazılan kod bloklarını sırasıyla biri durduruna kadar sonsuza kadar yazarlar.
loop {
println!("Başım dönüyoooo") // Sonsuza kadar bu mesajı yazdıracak
}
Bu döngü sonsuza kadar devam edecektir. Ancak istersek biz terminalde ctrl + c
ifadesini kullanarak durdurabiliriz.
Bu loop
değerlerini isimsiz de oluşturabileceğimiz gibi isimler ile de tanımlayabiliriz. Ancak bu isimleri verirken dikkat etmemiz gereken şey döngü isimlerinin başlarına kesme işareti '
koymaktır. Peki neden döngülere isim vermemiz bizim için önemli? Sizlere döngülerin sonsuz olduğunu ve birisi durdurmadıkça sonsuza kadar devam edeceğini söylemiştik, peki nasıl bu döngüyü durduracağız? İşte bu döngüleri durdurmak için break
methodumuz bulunmakta. Bu methodu döngünün içerisinde yalın olarak kullandığımızda en iç kısımında bulunan döngüyü kırmaktayız. Bu da bizi nested loop
yani iç içe döngü
kavramına getirmekte. Rust içerisinde istediğiniz kadar iç içe döngü oluşturmanız mümkün. Peki bir döngü zaten sonsuzken nasıl bu döngünün dışındaki döngü gerçekleşebilir? Hadi bir örnek ile bakalım.
loop {
println!("Merhaba");
loop {
println!("Nasılsın?");
}
}
Yukarda ifade edilen kodumuz bir iç içe döngü yani nested loop
olmaktadır. Bu kodu çalıştırdığımızda şu şekilde bir çıktı ile karşılaşacağız.
Merhaba
Nasılsın?
Nasılsın?
Nasılsın?
Nasılsın?
Nasılsın?
Nasılsın?
Nasılsın?
...
Gördüğünüz gibi kodumuz çalışmaya üstten aşşağı başladığı için Merhaba
ifadesini bir kez yazdırmış olsada altında bulunan döngüye girerek sonsuza kadar çıkamadı. Bu nedenle bir daha Merhaba
yazdırmadı. Ancak bu durumdan kurtulmak için bir yöntemimiz olmakta. İşte bu yöntem break
! Break yapısı kullanarak döngüden direkt olarak çıkış yapabiliriz. Şimdi kodumuza break ilave ederek bu işlemi yeniden deneyelim.
loop {
println!("Merhaba");
loop {
println!("Nasılsın?");
break
}
}
İç loop
içerisine break ibaresi ekledik. Şimdi çalıştırarak çıktıya bakalım:
Merhaba
Nasılsın?
Merhaba
Nasılsın?
Merhaba
Nasılsın?
...
Gördüğümüz gibi tamamen farklı bir sonuç oluştu. Kodumuzu şimdi satır satır inceleyelim. İlk olarak Merhaba
yazdırarak başladık. Sonrasında iç loop
'a girdik. Nasılsın?
yazdırdık. Bir satır altına indiğimizde break
anahtar kelimesine gelmekteyiz. Bu komut içinde bulunduğu loop
'u kırarak dışarı çıkar. Sonrasında dış loop yeniden işleme girerek bizlere Merhaba
yazdırır ve bu işlem sonsuza kadar devam eder.
Fark ettiğiniz gibi break
yapısı sadece içerisinde bulunduğu en son döngüyü kırmaktadır. Peki biz iç kısımdan daha dış bir döngüyü kırmak istesek bu işlemi nasıl yapabiliriz? İşte burada da karşımıza loop'ları isimlendirmenin nasıl işimize yarayacağı çıkmaktadır. Eğer bir loop'a isim verirsek ve sonrasında break anahtar kelimesinin yanına bu ismi koyarsak ne kadar içerde olursak olalım herhangi bir loop'u kırabiliriz. Bu durumu kod içerisinde inceleyecek olursak:
'en_buyuk: loop{
println!("Merhaba");
'orta_derece: loop{
println!("Nasılsın");
'en_kucuk: loop{
break 'en_buyuk;
}
}
}
Yukarıda kullandığımız kod yapısını break
'i yanlız bırakarak yazsaydık Merhaba
ve Nasılsın
ifadelerinin sonsuza kadar devam ettiğini görüntüleyecektik. Ancak bu şekilde yapmadığımız ve break 'en_buyuk
yapısı ile hangi döngüyü kıracağımızı belirttiğimiz için terminale sadece alt kısımda ifade edilen çıktı oluştu ve sonsuza kadar gitmeden direkt olarak durdu.
Merhaba
Nasılsın
Ayrıca
break
yapısınıif
ile birleştirerek nasıl döngülerden belirli şartlar oluşunca çıkabileceğinizi görüntüleyebilirsiniz.
While Döngüsü
While döngüsü türkçeye bir ek olan ederken
diye çevrilebilir. Yani bir cümle içerisinde kullanacak olursak "Eve gelince bana yardımederek
masayı kurabilirsin" ifadesi örnek verebiliriz. Her nasıl bu cümlede yardım etme
işi eve gelince
şartı ile birleştiyse while
döngüleri de belirli bir şartın true
olduğu her an çalışmakta olup false
olduğu anda çalışmayı bırakıyordur.
Bu duruma örnek vermek için 10'a kadar sayan bir program yazabiliriz.
let mut sayi = 0;
while sayi < 10{
println!("Sayımız: {}", sayi);
sayi = sayi + 1;
}
Bu şekilde yazdığımız kodu çalıştırınca while
döngüsünün yanında bulunan şart false
olana kadar çalıştığını görebiliriz.
Sayımız: 0
Sayımız: 1
Sayımız: 2
Sayımız: 3
Sayımız: 4
Sayımız: 5
Sayımız: 6
Sayımız: 7
Sayımız: 8
Sayımız: 9
Yukarıdaki kod çıktısında da görüntüleyebileceğimiz üzere sayi
değerimiz sürekli artarken 10'a eşit olduğu anda şart sağlanmamış ve döngü kırılarak bitmiştir.
Eğer kodumuzun 10'u da içermesini istiyorsak
<
yerine<=
ibaresini de kullanabiliriz.
Aynı zamanda while
loop'una özel olmadan her loop'da çalışan farklı bir değeri de yazdığımız kodda örnekleyebiliriz. Bu değer ise continue
olmakta. Diyelim ki 10'a kadar sayılarımızı yazdırdık ancak 7 değeri bize uğursuz geldi canımız istemedi ve döngüden çıkarmak istedik. İşte tam bu anda continue
yapısını kullanabiliriz. continue
yapısı çalıştığı anda kodumuz sonrasında bulunan işlemleri yapmadan yeniden çalışır ki bu bizim durumumuzda bir sayı atlaması anlamına gelmekedir. Hadi kodumuzu if
ve continue
ifadeleri ile 7'yi atlayan bir hale getirelim.
let mut sayi = 0;
while sayi < 10{
if sayi == 7{
sayi += 1;
continue;
}else{
println!("Sayı: {}", sayi);
sayi = sayi + 1
}
}
Kodumuzu çalıştırdığımızda görüntüleyebileceğiniz üzere 7 sayısı olmadan tüm çıktılar sorunsuz bir şekilde ekrana gelmektedir.
Sayı: 0
Sayı: 1
Sayı: 2
Sayı: 3
Sayı: 4
Sayı: 5
Sayı: 6
Sayı: 8
Sayı: 9
For Döngüsü
For döngüleri belirli bir koleksiyondaki elementler için bir işlemi tekarlamanın mükemmel bir yoludur. Örneğin bir vektör!
Hadi bir örnek yapalım. Diyelim ki bir vektörümüz var ve bu vekörün içerinde 1'den 10'a kadar sayılar var. Bizde bu sayıları yazdırmak istiyoruz. Bu işlem için alt kısımda bulunduğu gibi bir döngü yazmamız gerekmektedir.
let sayilar: Vec<i8> = (0..10).collect();
for sayi in sayilar{
println!("Sayı: {}", sayi);
}
Sırasıyla kodumuza bakıcak olursak ilk olarak [0,10) aralığında bir vektör oluşurup bu vektöre sayilar
adını vermişiz. Sonrasında for döngüsü karşımıza çıkmış. Bu döngüyü "sayilar
vektörünün içerisindeki
(in) her bir değeri sırasıyla sayi
değişkenine eşitle ve sonrasında ekrana yazdır" şeklinde türkçeleştirebiliriz. Kodumuzu çalıştırırsak alt kısımdaki gibi bir sonuç çıkacağını görüntüleyebiliriz.
Sayılar: 0
Sayılar: 1
Sayılar: 2
Sayılar: 3
Sayılar: 4
Sayılar: 5
Sayılar: 6
Sayılar: 7
Sayılar: 8
Sayılar: 9
Aynı zamanda vektörü for döngüsünde
in
ifadesinden sonrafor sayi in (1..10){...}
şeklinde tanımlayabiliriz.